<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
 *连心卡PC官网向支付通请求数据封装类
 * @author luke 2017.10.16
 */
class DataFromzft{
	private $url;//请求地址
	private $appkey;//商户id
	private $appsecret;//私钥
	private $CI;//框架类实例
	private $apilog;//接口日志

	/**
	 * 构造函数
	 * @param null
	 * @return null
	 * @author luke 2017.10.15
	 */
	public function __construct()
	{
		$this->CI = & get_instance();
		$this->url = $this->CI->config->item("URL");
		$this->appsecret = $this->CI->config->item("APP_SECRET");
		$this->appkey = $this->CI->config->item("APP_KEY");
		$this->CI->load->library("Apilog");
		$this->apilog = $this->CI->apilog;
	}

	/**
	 * 卡信息查询接口
	 * @param $card_id 卡号
	 * @return array rsp_code=0000为成功 其他为失败 msg为返回描述信息  data返回null
	 * end_dt yyyyMMdd	卡有效日期
	 * avail_at 10000（100元）	可用余额
	 * bal_at 10000（100元）	账户余额
	 * @author luke 2017.10.16
	 */
	public function cardInfo($card_id = ""){
		if(empty($card_id)){return array("error"=>-1,"msg"=>"参数不完整");exit;}
		date_default_timezone_set('PRC');
		$rqtimestamp = time();
		$data = array();
		$data['app_key'] = $this->appkey;
		$data['timestamp'] = date("YmdHis",$rqtimestamp);
		$data['v'] = "1.0";
		$data['sign_v'] = "1";
		$data['format'] = "json";
		$data['method'] = "allinpay.ggpt.ecard.cardinfo.get";
		$data['req_seq'] = substr($rqtimestamp,4,7).rand(0000,9999);
		$data['req_dt'] = date("Ymd",$rqtimestamp);
		$data['req_tm'] = date("His",$rqtimestamp);
		$data['card_id'] = $card_id;
		$data['sign'] = $this->sign($data);
		$result = $this->post($this->url,$data);
		if(empty($result)){
			$msg = "未收到响应数据";
			$this->apilog->addlog(102,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$result);
			return array("error"=>-1,"msg"=>$msg);
			exit;
		}
		$res = json_decode($result,true);
		if(isset($res['error_response'])){
			$msg = isset($res['error_response']['sub_msg'])?$res['error_response']['sub_msg']:"未知错误请查看日志";
			$this->apilog->addlog(102,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$this->json_my_encode($res));
			return array("error"=>-1,"msg"=>$msg);
			exit;
		}
		$result = $res['ggpt_ecard_cardinfo_get_response'];
		if(!is_array($result) || !isset($result['rsp_code'])){
			$msg = "响应数据格式有误";
			$this->apilog->addlog(102,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$this->json_my_encode($res));
			return array("error"=>-1,"msg"=>$msg);
			exit;
		}
		if($result['rsp_code'] != 0000){
			$msg = "错误;".$result['ret_msg'];
			$this->apilog->addlog(102,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$this->json_my_encode($res));
			return array("error"=>-1,"msg"=>$msg);
			exit;
		}
		$msg = "卡信息查询成功";
		$this->apilog->addlog(102,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$this->json_my_encode($res));
		return array("error"=>0,"msg"=>$msg,"data"=>$result);
		exit;
	}

	/**
	 * 预付卡密码验证接口
	 * @param $card_id 卡号
	 * @param $password 卡密
	 * @param $opr_id 操作员
	 * @return array rsp_code=0000为成功 其他为失败 msg为返回描述信息  data返回null
	 * @author luke 2017.10.16
	 */
	public function cardVerify($card_id = "",$password = "",$opr_id = ""){
		if(empty($card_id) || empty($password) || empty($opr_id)){return array("error"=>-1,"msg"=>"参数不完整");exit;}
		date_default_timezone_set('PRC');
		$rqtimestamp = time();
		$data = array();
		$data['app_key'] = $this->appkey;
		$data['timestamp'] = date("YmdHis",$rqtimestamp);
		$data['v'] = "1.0";
		$data['sign_v'] = "1";
		$data['format'] = "json";
		$data['method'] = "allinpay.ggpt.ecard.cardpassword.verify";
		$data['req_seq'] = substr($rqtimestamp,4,7).rand(0000,9999);
		$data['req_dt'] = date("Ymd",$rqtimestamp);
		$data['req_tm'] = date("His",$rqtimestamp);
		$data['card_id'] = $card_id;
		$data['password'] = $password;
		$data['opr_id'] = $opr_id;
		$data['sign'] = $this->sign($data);
		$result = $this->post($this->url,$data);
		if(empty($result)){
			$msg = "未收到响应数据";
			$this->apilog->addlog(103,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$result);
			return array("error"=>-1,"msg"=>$msg);
			exit;
		}
		$res = json_decode($result,true);
		if(isset($res['error_response'])){
			$msg = isset($res['error_response']['sub_msg'])?$res['error_response']['sub_msg']:"未知错误请查看日志";
			$this->apilog->addlog(103,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$this->json_my_encode($res));
			return array("error"=>-1,"msg"=>$msg);
			exit;
		}
		$result = $res['ggpt_ecard_cardpassword_verify_response'];
		if(!is_array($result) || !isset($result['rsp_code'])){
			$msg = "响应数据格式有误";
			$this->apilog->addlog(103,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$this->json_my_encode($res));
			return array("error"=>-1,"msg"=>$msg);
			exit;
		}

		if($result['rsp_code'] != 0000){
			$msg = "错误;".$result['rsp_msg'];
			$this->apilog->addlog(103,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$this->json_my_encode($res));
			return array("error"=>1,"msg"=>$msg,"last_err_times"=>$result['last_err_times']);
			exit;
		}
		$msg = "卡密验证成功";
		$this->apilog->addlog(103,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$this->json_my_encode($res));
		return array("error"=>0,"msg"=>$msg,"data"=>$result);
		exit;
	}

	/**
	 * 修改卡密码接口
	 * @param $card_id 卡号
	 * @param $password 卡密
	 * @param $new_password 新卡密
	 * @param $opr_id 操作员
	 * @return array rsp_code=0000为成功 其他为失败 msg为返回描述信息  data返回null
	 * last_err_times 剩余可错误次数
	 * rsp_msg 错误信息
	 * @author luke 2017.10.16
	 */
	public function cardChange($card_id = "",$password = "",$new_password = "",$opr_id=""){
		if(empty($card_id) || empty($password) || empty($new_password) || empty($opr_id)){return array("error"=>-1,"msg"=>"参数不完整");exit;}
		date_default_timezone_set('PRC');
		$rqtimestamp = time();
		$data = array();
		$data['app_key'] = $this->appkey;
		$data['timestamp'] = date("YmdHis",$rqtimestamp);
		$data['v'] = "1.0";
		$data['sign_v'] = "1";
		$data['format'] = "json";
		$data['method'] = "allinpay.ggpt.ecard.cardpassword.change";
		$data['req_seq'] = substr($rqtimestamp,4,7).rand(0000,9999);
		$data['req_dt'] = date("Ymd",$rqtimestamp);
		$data['req_tm'] = date("His",$rqtimestamp);
		$data['cust_id'] = $card_id;
		$data['opr_id'] = $opr_id;
		$data['old_password'] = $password;
		$data['password'] = $new_password;
		$data['pwd_flg'] = "1";
		$data['sign'] = $this->sign($data);
		$result = $this->post($this->url,$data);
		if(empty($result)){
			$msg = "未收到响应数据";
			$this->apilog->addlog(104,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$result);
			return array("error"=>-1,"msg"=>$msg);
			exit;
		}
		$res = json_decode($result,true);
		if(isset($res['error_response'])){
			//已挂失
			if(isset($res['error_response']['sub_code']) && $res['error_response']['sub_code'] == 1050){
				$msg = isset($res['error_response']['sub_msg'])?$res['error_response']['sub_msg']:"未知错误请查看日志";
				$this->apilog->addlog(104,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$this->json_my_encode($res));
				return array("error"=>-2,"msg"=>$msg);
				exit;
			}else{
				//其他异常情况
				$msg = isset($res['error_response']['sub_msg'])?$res['error_response']['sub_msg']:"未知错误请查看日志";
				$this->apilog->addlog(104,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$this->json_my_encode($res));
				return array("error"=>-1,"msg"=>$msg);
				exit;
			}
		}
		$result = $res['ggpt_ecard_cardpassword_change_response'];
		if(!is_array($result) || !isset($result['rsp_code'])){
			$msg = "响应数据格式有误";
			$this->apilog->addlog(104,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$this->json_my_encode($res));
			return array("error"=>-1,"msg"=>$msg);
			exit;
		}
		if($result['rsp_code'] != 0000){
			$msg = "错误;".$result['rsp_msg'];
			$this->apilog->addlog(104,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$this->json_my_encode($res));
			return array("error"=>1,"msg"=>$msg,"last_err_times"=>$result['last_err_times']);
			exit;
		}
		$msg = "修改卡密成功";
		$this->apilog->addlog(104,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$this->json_my_encode($res));
		return array("error"=>0,"msg"=>$msg,"data"=>$result);
		exit;
	}

	/**
	 * 卡交易记录查询接口
	 * @param $card_id 卡号
	 * @param $page_no 分页页号（不超过10位）
	 * @param $page_size 单页记录条数（不超过12位）
	 * @param $min_txn_at 最小交易金额(不超过12位)
	 * @param $max_txn_at 最大交易金额(不超过12位)
	 * @param $begin_date 起始日期	yyyyMMdd
	 * @param $end_date 截止日期	yyyyMMdd
	 * @return array rsp_code=0000为成功 其他为失败 msg为返回描述信息  data返回null
	 * total 10	总记录数
	 * custId	卡号
	 * availBalAt`可用余额	单位为分
	 * intTxnDt	交易日期	yyyyMMdd
	 * txnAt`交易金额	单位为分
	 * acctBalAt`账户余额	单位为分
	 * openBrhId`开户机构号	中国支付通分配
	 * merId`商户号	中国支付通分配
	 * termId`受理终端号
	 * accessTxnDt`请求交易日期	yyyyMMdd
	 * accessTxnTm`请求交易时间	HHmmss
	 * txnStaCd`交易状态0	挂起 1	失败 2	成功 3	已冲正 4	已取消
	 * txnCd`交易类型码
	 * 	A0010	客户开户
		C0016	账户充值直充
		B0010	消费
		B0012 	消费冲正
		B0013 	消费撤销
		F0020 	账户冻结
		F0021 	账户解冻
		F0060	卡密码重置
		F0061 	卡密码修改
		A00112 	产品绑定
		B0030	账户转账
		A0040	客户开户
		A0041	客户退卡
	 * intTxnSeqId	交易流水号
	 * accessRefSeqId`接入方参考号
	 * txnFeeAt`交易手续费	单位为分
	 * intTxnTm`交易时间	HHmmss
	 * merNm`商户名称
	 * prdtNo`产品号	中国支付通分配
	 * prdtType`产品类型
	 * @author luke 2017.10.16
	 */
	public function cardTxnLog($card_id = "",$page_no="0",$page_size="10",$begin_date="",$end_date = "",$min_txn_at="",$max_txn_at=""){
		if(empty($card_id)){return array("error"=>-1,"msg"=>"参数不完整");exit;}
		date_default_timezone_set('PRC');
		$rqtimestamp = time();
		$data = array();
		$data['app_key'] = $this->appkey;
		$data['timestamp'] = date("YmdHis",$rqtimestamp);
		$data['v'] = "1.0";
		$data['sign_v'] = "1";
		$data['format'] = "json";
		$data['method'] = "allinpay.ggpt.ecard.txnlog.getAll";
		$data['card_id'] = $card_id;
		$data['page_no'] = $page_no;
		$data['page_size'] = $page_size;
		$data['txn_cd'] = "B00100|B00101|B00102|B00103|B00104|B00105|B00106|B00107|B00108|B00109|B0010A|B0010B|B0010E|B0010F|B0010H|B00110|B00111|B00112|B00113|B00114|B00115|B00116|B00119|B0011E|B0011F|B00120|B00121|B00122|B00123|B00124|B00126|B00129|B0012E|B00130|B00131|B00132|B00133|B00134|B00139|B00200|B00202|B0020E|B00510|B00710|B00712|B0071B|B00730|B00731|B00734|B00735|B00736|B00738|B00739|B0073B|B0073E|B0073F|Z12210|";
		if(!empty($begin_date)){
			$data['begin_date'] = $begin_date;
		}
		if(!empty($end_date)){
			$data['end_date'] = $end_date;
		}
		if(!empty($min_txn_at)){
			$data['min_txn_at'] = $min_txn_at;
		}
		if(!empty($max_txn_at)){
			$data['max_txn_at'] = $max_txn_at;
		}
		$data['sign'] = $this->sign($data);
		$result = $this->post($this->url,$data);
		if(empty($result)){
			$msg = "未收到响应数据";
			$this->apilog->addlog(105,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$result);
			return array("error"=>-1,"msg"=>$msg);
			exit;
		}
		$res = json_decode($result,true);
		if(isset($res['error_response'])){
			$msg = isset($res['error_response']['sub_msg'])?$res['error_response']['sub_msg']:"未知错误请查看日志";
			$this->apilog->addlog(105,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$this->json_my_encode($res));
			return array("error"=>-1,"msg"=>$msg);
			exit;
		}
		$result = $res['ggpt_ecard_txnlog_getAll_response'];
		if(!is_array($result) || !isset($result['rsp_code'])){
			$msg = "响应数据格式有误";
			$this->apilog->addlog(105,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$this->json_my_encode($res));
			return array("error"=>-1,"msg"=>$msg);
			exit;
		}
		if($result['rsp_code'] != 0000){
			$msg = "错误;".$result['ret_msg'];
			$this->apilog->addlog(105,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$this->json_my_encode($res));
			return array("error"=>-1,"msg"=>$msg);
			exit;
		}
		$msg = "交易记录查询成功";
		$this->apilog->addlog(105,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$this->json_my_encode($res));
		return array("error"=>0,"msg"=>$msg,"data"=>$result);
		exit;
	}

	/**
	 * 预付卡挂失解挂接口
	 * @param $card_id 卡号
	 * @param $id_no 证件号
	 * @param $id_type 证件类型
	 *  1	身份证
		2	户口本
		3	护照
		4	军人证
		5	回乡证
		6	居住证
		7	驾照
		8	企业代码证
		9	经营许可证
		A	营业执照
		B	事业法人证
		C 	台胞证
		D 	社会保险证
	 * @param $reason 操作原因
	 * @param $flag 0表示挂失，非0表示解除挂失
	 * @return array rsp_code=0000为成功 其他为失败 msg为返回描述信息  data返回null
	 * @author luke 2017.10.16
	 */
	public function cardLost($card_id = "",$id_no = "",$id_type="",$reason = "",$flag="0"){
		if(empty($card_id) || empty($id_no) || empty($id_type)){return array("error"=>-1,"msg"=>"参数不完整");exit;}
		if(strlen($id_no) != 18 && strlen($id_no) != 15){return array("error"=>-1,"msg"=>"身份证号位数不正确");exit;}
		if(!in_array($flag,array(0,1))){return array("error"=>-1,"msg"=>"标志位不正确");exit;}
		date_default_timezone_set('PRC');
		$rqtimestamp = time();
		$data = array();
		$data['app_key'] = $this->appkey;
		$data['timestamp'] = date("YmdHis",$rqtimestamp);
		$data['v'] = "1.0";
		$data['sign_v'] = "1";
		$data['format'] = "json";
		$data['method'] = "allinpay.ggpt.cardticket.card.lose";
		$data['req_seq'] = substr($rqtimestamp,4,7).rand(0000,9999);
		$data['req_dt'] = date("Ymd",$rqtimestamp);
		$data['req_tm'] = date("His",$rqtimestamp);
		$data['card_id'] = $card_id;
		$data['id_no'] = $id_no;
		$data['id_type'] = $id_type;
		if(!empty($reason)){
			$data['reason'] = $reason;
		}
		$data['flag'] = $flag;
		$data['sign'] = $this->sign($data);
		$result = $this->post($this->url,$data);
		if(empty($result)){
			$msg = "未收到响应数据";
			$this->apilog->addlog(106,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$result);
			return array("error"=>-1,"msg"=>$msg);
			exit;
		}
		$res = json_decode($result,true);
		if(isset($res['error_response'])){
			$msg = isset($res['error_response']['sub_msg'])?$res['error_response']['sub_msg']:"未知错误请查看日志";
			$this->apilog->addlog(106,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$this->json_my_encode($res));
			return array("error"=>-1,"msg"=>$msg);
			exit;
		}
		$result = $res['ggpt_cardticket_card_lose_response'];
		if(!is_array($result) || !isset($result['rsp_code'])){
			$msg = "响应数据格式有误";
			$this->apilog->addlog(106,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$this->json_my_encode($res));
			return array("error"=>-1,"msg"=>$msg);
			exit;
		}
		if($result['rsp_code'] == 1050){
			//已挂失，无需重复挂失
			$msg = "错误;".$result['ret_msg'];
			$this->apilog->addlog(106,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$this->json_my_encode($res));
			return array("error"=>-1,"msg"=>$msg);
			exit;
		}
		if($result['rsp_code'] != 0000){
			$msg = "错误;".$result['ret_msg'];
			$this->apilog->addlog(106,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$this->json_my_encode($res));
			return array("error"=>-2,"msg"=>$msg);
			exit;
		}
		$msg = "挂失成功";
		$this->apilog->addlog(106,$rqtimestamp,time(),0,$card_id,$msg,$this->json_my_encode($data),$this->json_my_encode($res));
		return array("error"=>0,"msg"=>$msg,"data"=>$result);
		exit;
	}

	/**
	 * 签名
	 * @param $data需要签名的数组
	 * @return string md5后的字符串
	 * @author luke 2017.10.16
	 */
	private function sign($params){
		ksort($params);
		$stringToBeSigned = $this->appsecret;
		foreach ($params as $k => $v) {
				$stringToBeSigned .= "$k$v";
		}
		unset($k, $v);
		$stringToBeSigned .= $this->appsecret;
		return strtoupper(md5($stringToBeSigned));
	}

	/**
	 * post方法
	 */
	private function post($url,$data,$second=30){
		$headers = array(
			"Content-Type: application/x-www-form-urlencoded;charset=UTF-8",
			"Accept: application/json",
			"Cache-Control: no-cache",
			"Pragma: no-cache"
		);
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_TIMEOUT, $second);
		curl_setopt($ch,CURLOPT_URL, $url);
		curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
		curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);//严格校验
		//设置header
		curl_setopt($ch, CURLOPT_HEADER, FALSE);
		//要求结果为字符串且输出到屏幕上
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
		curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
		//post提交方式
		curl_setopt($ch, CURLOPT_POST, TRUE);
		curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
		//运行curl
		$data = curl_exec($ch);
		curl_close($ch);
		return $data;
	}

	/**
	 * 自定义$this->json_my_encode函数
	 * @param $data array
	 * @return json string
	 * @author luke 2017.10.15
	 */
	private function json_my_encode($data){
		$str = json_encode( $data);
		$str =  preg_replace_callback(
			"#\\\u([0-9a-f]{4})#i",
			function( $matchs)
			{
				return  iconv('UCS-2BE', 'UTF-8',  pack('H4',  $matchs[1]));
			},
			$str
		);
		return  $str;
	}
}